From ce3d4a4111a5f7e6b4e74bceae5faa6ce388e8ec Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Sun, 14 Jul 2013 23:08:11 +0200
Subject: [PATCH 05/53] MIPS: use set_mode() to enable/disable the cevt-r4k
 irq

Signed-off-by: John Crispin <blogic@openwrt.org>
---
 arch/mips/ralink/Kconfig |    5 +++++
 1 file changed, 5 insertions(+)

--- a/arch/mips/ralink/Kconfig
+++ b/arch/mips/ralink/Kconfig
@@ -1,12 +1,17 @@
 # SPDX-License-Identifier: GPL-2.0
 if RALINK
 
+config CEVT_SYSTICK_QUIRK
+	bool
+	default n
+
 config CLKEVT_RT3352
 	bool
 	depends on SOC_RT305X || SOC_MT7620
 	default y
 	select TIMER_OF
 	select CLKSRC_MMIO
+	select CEVT_SYSTICK_QUIRK
 
 config RALINK_ILL_ACC
 	bool
--- a/arch/mips/kernel/cevt-r4k.c
+++ b/arch/mips/kernel/cevt-r4k.c
@@ -16,6 +16,31 @@
 #include <asm/time.h>
 #include <asm/cevt-r4k.h>
 
+#ifdef CONFIG_CEVT_SYSTICK_QUIRK
+static int mips_state_oneshot(struct clock_event_device *evt)
+{
+	unsigned long flags = IRQF_PERCPU | IRQF_TIMER | IRQF_SHARED;
+	if (!cp0_timer_irq_installed) {
+		cp0_timer_irq_installed = 1;
+		if (request_irq(evt->irq, c0_compare_interrupt, flags, "timer",
+					c0_compare_interrupt))
+			pr_err("Failed to request irq %d (timer)\n", evt->irq);
+	}
+
+	return 0;
+}
+
+static int mips_state_shutdown(struct clock_event_device *evt)
+{
+	if (cp0_timer_irq_installed) {
+		cp0_timer_irq_installed = 0;
+		free_irq(evt->irq, NULL);
+	}
+
+	return 0;
+}
+#endif
+
 static int mips_next_event(unsigned long delta,
 			   struct clock_event_device *evt)
 {
@@ -292,7 +317,9 @@ core_initcall(r4k_register_cpufreq_notif
 
 int r4k_clockevent_init(void)
 {
+#ifndef CONFIG_CEVT_SYSTICK_QUIRK
 	unsigned long flags = IRQF_PERCPU | IRQF_TIMER | IRQF_SHARED;
+#endif
 	unsigned int cpu = smp_processor_id();
 	struct clock_event_device *cd;
 	unsigned int irq, min_delta;
@@ -322,11 +349,16 @@ int r4k_clockevent_init(void)
 	cd->rating		= 300;
 	cd->irq			= irq;
 	cd->cpumask		= cpumask_of(cpu);
+#ifdef CONFIG_CEVT_SYSTICK_QUIRK
+	cd->set_state_shutdown	= mips_state_shutdown;
+	cd->set_state_oneshot	= mips_state_oneshot;
+#endif
 	cd->set_next_event	= mips_next_event;
 	cd->event_handler	= mips_event_handler;
 
 	clockevents_config_and_register(cd, mips_hpt_frequency, min_delta, 0x7fffffff);
 
+#ifndef CONFIG_CEVT_SYSTICK_QUIRK
 	if (cp0_timer_irq_installed)
 		return 0;
 
@@ -335,6 +367,7 @@ int r4k_clockevent_init(void)
 	if (request_irq(irq, c0_compare_interrupt, flags, "timer",
 			c0_compare_interrupt))
 		pr_err("Failed to request irq %d (timer)\n", irq);
+#endif
 
 	return 0;
 }
